package com.powernode.service.impl;

import com.powernode.component.LoginUserHolder;
import com.powernode.constant.RedisConstant;
import com.powernode.dto.ProductDto;
import com.powernode.dto.Result;
import com.powernode.exception.BizException;
import com.powernode.feign.PMSFeign;
import com.powernode.model.CartItem;
import com.powernode.service.CartItemService;
import com.powernode.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class CartItemServiceImpl implements CartItemService {
    @Autowired
    private PMSFeign feign;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LoginUserHolder holder;

    /**
     * 获取redis库中购物车的key
     * key组成：cart:{userId}
     */
    private String key(){
        return RedisConstant.KEY_CART + holder.getLoginUserId();
    }

    /**
     * 添加商品到购物车
     */
    @Override
    public CartItem addToCart(Long id) {
        Result<ProductDto> result = feign.getProductById(id);
        // 如果请求错误，返回错误信息
        if (result.getCode() != HttpStatus.OK.value()) {
            throw new BizException(result.getCode(), result.getMessage());
        }
        // 如果商品为null，响应信息
        ProductDto productDto = result.getData();
        if (productDto == null) {
            throw new BizException(HttpStatus.NOT_FOUND.value(), "商品不存在或已下架");
        }
        // 商品存在，判断是否在购物车中存在

        CartItem cartItem = (CartItem) redisUtil.hget(key(),String.valueOf(id));
        if (cartItem == null) {
            // 如果商品在购物车不存在，新增到购物车，商品数量为1
            cartItem = new CartItem();
            cartItem.setCount(1);
        }else {
            // 商品在购物车存在，商品数量加1
            cartItem.setCount(cartItem.getCount()+1);
            // 设置更新时间
            cartItem.setUpdateTime(new Date());
        }
        // copyBean
        BeanUtils.copyProperties(productDto,cartItem);
        // 将商品添加到redis
        redisUtil.hset(key(),String.valueOf(id),cartItem);

        return cartItem;
    }

    /**
     * 获取购物车所有商品
     */
    @Override
    public List<CartItem> getAll() {
        // 从redis中获取所有商品
        List<Object> objectList = Arrays.asList(redisUtil.hmget(key()).values().toArray());
        List<CartItem> list = new ArrayList<>();
        // 存储到一个list集合
        objectList.forEach(item -> list.add((CartItem) item));
        // 对商品按时间排序
        list.sort((o1, o2) -> - o1.getUpdateTime().compareTo(o2.getUpdateTime()));
        return list;
    }

    /**
     * 更新购物车中商品数量
     */
    @Override
    public void updateCount(Long id, Integer count) {

        if (count < 0){
            throw new BizException(HttpStatus.BAD_REQUEST.value(), "商品数量至少一个以上");
        }
        // 如果数量为0，则删除
        if (count == 0){
            this.deleteById(id);
        }
        //
        CartItem cartItem = (CartItem) redisUtil.hget(key(),String.valueOf(id));
        // 更新商品数量
        cartItem.setCount(count);
        cartItem.setUpdateTime(new Date());
        // 更新redis
        redisUtil.hset(key(),String.valueOf(id),cartItem);
    }

    /**
     * 商品选中或取消选中
     */
    @Override
    public void checked(Long id, boolean checked) {

        CartItem cartItem = (CartItem) redisUtil.hget(key(),String.valueOf(id));
        // 更新
        cartItem.setChecked(checked);
        // 更新到redis
        redisUtil.hset(key(),String.valueOf(id),cartItem);
    }

    /**
     * 全选或取消全选
     */
    @Override
    public void checkAll(boolean checked) {
        Map<String,Object> map = new HashMap<>();
        this.getAll().forEach(item -> {
            item.setChecked(checked);
            map.put(String.valueOf(item.getId()),item);
        });
        // 更新到redis
        redisUtil.hmset(key(),map);
    }

    /**
     * 根据商品id删除购物车中的商品
     */
    @Override
    public void deleteById(Long id) {

        redisUtil.hdel(key(), String.valueOf(id));
    }

    /**
     * 清购物车
     */
    @Override
    public void deleteAll() {
        redisUtil.del(key());
    }
}
